package errchk_manip

import (
	"fmt"
	"go/ast"
	"strings"
	"manip_exec"
)

type ErrManipulator struct {
}

var astNodes = make([]ast.Node, 0)

func (m ErrManipulator) ManipulateAST(f ast.Node, index int) (manip_exec.ManiRes, error) {

	astNodes = make([]ast.Node, 0)		//This has to be reset as well

	// Walk through the AST & Build astNodes
	v := astVisitor{}
	ast.Walk(v, f)

	errIdents := make([]*ast.Ident, 0)

	for _, v := range astNodes {

		switch x := v.(type) {
		case *ast.Ident:
			if strings.Contains(x.String(), "err") {
				errIdents = append(errIdents, x)
				//fmt.Println(x.String())
			}
		}
	}
	var random int
	if len(errIdents) > 0 {
	random = index % len(errIdents)
	} else {		//Force build failure
		astNodes[0] = nil
		retString := "Nothing manipulated"
		result := manip_exec.ManiRes{[]int{}, retString}
		return result, nil		
	}

	changedIdent := errIdents[random].Name
	errIdents[random].Name = "_"

	defer func() {
		if e := recover(); e != nil {
			fmt.Println("Here was an error...")
		}
	}()

	retString := fmt.Sprintf("Changed %s to _ in Line: ", changedIdent)
	result := manip_exec.ManiRes{[]int{int(errIdents[random].Pos())}, retString}

	return result, nil

}

func (m ErrManipulator) String() string {
	return "errchk"
}

//Walker Vistor struct
type astVisitor struct {
}

//Walker Visitor function
func (v astVisitor) Visit(node ast.Node) (w ast.Visitor) {
	if node != nil {

		astNodes = append(astNodes, node) //Builds the Node Slice
	}
	return ast.Visitor(v)
}

